home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / mail / pp / pp-6.0 / Src / MTAconsole / badness.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-12-18  |  19.5 KB  |  957 lines

  1. /* badness.c: routines calculating and using "badness" */
  2.  
  3. # ifndef lint
  4. static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Src/MTAconsole/RCS/badness.c,v 6.0 1991/12/18 20:26:48 jpo Rel $";
  5. # endif
  6.  
  7. /*
  8.  * $Header: /xtel/pp/pp-beta/Src/MTAconsole/RCS/badness.c,v 6.0 1991/12/18 20:26:48 jpo Rel $
  9.  *
  10.  * $Log: badness.c,v $
  11.  * Revision 6.0  1991/12/18  20:26:48  jpo
  12.  * Release 6.0
  13.  *
  14.  */
  15.  
  16.  
  17.  
  18. #include    "console.h"
  19.  
  20. #define    DEFAULT_TOTAL_NUMBER    10000.0
  21. #define DEFAULT_TOTAL_VOLUME    1000000.0
  22. struct tailor    *tailors = NULL;
  23. extern double     atof();
  24. extern char    tailorfile[];
  25. extern int    max_vert_lines;
  26. extern time_t   currentTime;
  27. extern char    *compress();
  28. double    ub_total_number = DEFAULT_TOTAL_NUMBER, 
  29.     ub_total_volume = DEFAULT_TOTAL_VOLUME;
  30. extern Display    *disp;
  31.  
  32. /*   */
  33.  
  34. static double    parse_ub(ub)
  35. char    *ub;
  36. {
  37.     double    pre;
  38.     char    *end;
  39.     pre = strtod(ub, &end);
  40.     
  41.     while (*end != '\0' && isspace(*end)) end++;
  42.     if (*end != '\0') {
  43.         switch    (*end) {
  44.             case 'h':
  45.             pre *= 60.0;
  46.             break;
  47.             case 'd':
  48.             pre *= 24.0 * 60.0;
  49.             break;
  50.             case 'k':
  51.             pre *= 1000.0;
  52.             break;
  53.             case 'M':
  54.             pre *= 1000000.0;
  55.             break;
  56.             default:
  57.             break;
  58.         }
  59.     }
  60.     return    pre;
  61. }
  62.  
  63. static void    add_total_ubs(entry)
  64. char    *entry;        
  65. {
  66.     char    *ix, *str, *margv[20];
  67.     int    i, margc;
  68.     char    *buf = strdup(entry);
  69.     
  70.     if ((ix = index(buf, ':')) == NULL) {
  71.         PP_LOG(LLOG_EXCEPTIONS,
  72.                ("Incorrect console tailor file entry '%s'",buf));
  73.         free(buf);
  74.         return;
  75.     }
  76.     ix++;
  77.     compress(ix, ix);
  78.     margc = sstr2arg(ix, 20, margv, ",");
  79.     i = 0;
  80.     while (i < margc) {
  81.         if ((ix = index(margv[i], '<')) != NULL) {
  82.             *ix = '\0';
  83.             str = margv[i];
  84.             ix++;
  85.             while(*ix != '\0' && isspace(*ix)) ix++;
  86.             while(*str != '\0' && isspace(*str)) str++;
  87.             if (*ix == '\0' || *str == '\0')
  88.                 return;
  89.             if (strncmp(str, "num", 3) == 0)
  90.                 ub_total_number = parse_ub(ix);
  91.             else if (strncmp(str, "vol", 3) == 0)
  92.                 ub_total_volume = parse_ub(ix);
  93.             else
  94.                 PP_LOG(LLOG_EXCEPTIONS,
  95.                        ("Unknown console tailor variable '%s'",
  96.                     str));
  97.         }
  98.         i++;
  99.     }
  100.     free(buf);
  101. }
  102.     
  103. static struct tailor    *tailor_new(entry)
  104. char    *entry;
  105. {
  106.     struct tailor     *ret;
  107.     char        *ix, *str, *margv[20];
  108.     int        i, margc;
  109.     char        *buf = strdup(entry);
  110.     ret = (struct tailor *) calloc(1, sizeof(*ret));
  111.  
  112.     if ((ix = index(buf, ':')) == NULL) {
  113.         PP_LOG(LLOG_EXCEPTIONS,
  114.                ("Incorrect console tailor file entry '%s'",buf));
  115.         free((char *) ret);
  116.         free(buf);
  117.         return NULL;
  118.     }
  119.     *ix = '\0';
  120.     ret->key = strdup(buf);
  121.     ix++;
  122.     compress(ix, ix);
  123.     margc = sstr2arg(ix, 20, margv, ",");
  124.  
  125.     i = 0;
  126.     while (i < margc) {
  127.         if ((ix = index(margv[i], '<')) != NULL) {
  128.             *ix = '\0';
  129.             str = margv[i];
  130.             ix++;
  131.             while (*ix != '\0' && isspace(*ix)) ix++;
  132.             while (*str != '\0' && isspace(*str)) str++;
  133.             if (*ix == '\0' || *str == '\0')
  134.                 return NULL;
  135.  
  136.             if (strncmp(str, "num", 3) == 0) 
  137.                 ret->ub_number = parse_ub(ix);
  138.             else if (strncmp(str, "vol", 3) == 0) 
  139.                 ret->ub_volume = parse_ub(ix);
  140.             else if (strncmp(str, "age", 3) == 0) 
  141.                 ret->ub_age = parse_ub(ix);
  142.             else if (strncmp(str, "las", 3) == 0) 
  143.                 ret->ub_last = parse_ub(ix);
  144.             else
  145.                 PP_LOG(LLOG_EXCEPTIONS,
  146.                        ("Unknown console tailor variable '%s'",
  147.                     str));
  148.         }
  149.         i++;
  150.     }
  151.     free(buf);
  152.     return ret;
  153. }
  154.  
  155. static void tailor_add(plist, new)
  156. struct tailor    **plist, *new;
  157. {
  158.     new->next = *plist;
  159.     *plist = new;
  160. }
  161.  
  162. void tailor_free(list)
  163. struct tailor    *list;
  164. {
  165.     if (list->key) free(list->key);
  166.     if (list->next) tailor_free(list->next);
  167.     free((char *) list);
  168. }
  169.  
  170. /*   */
  171.  
  172. struct tailor *find_tailor(name, list)
  173. char        *name;
  174. struct tailor    *list;
  175. {
  176.     while (list != NULL
  177.            && strcmp(list->key, name) != 0)
  178.         list = list->next;
  179.     return list;
  180. }
  181.  
  182. /*   */
  183. #include    "tai_defs.inc"
  184. extern char    *myname;
  185.  
  186. static void tailor_add_one_default(plist, type, hardwired)
  187. struct tailor    **plist;
  188. char        *type,
  189.         *hardwired;
  190. {
  191.     char    *temp,
  192.         buf[BUFSIZ];
  193.     if (find_tailor(type, *plist) == NULL) {
  194.         if ((temp = XGetDefault(disp, myname, type)) != NULL) {
  195.             sprintf(buf, "%s:%s",type,temp);
  196.             tailor_add(plist, tailor_new(buf));
  197.         } else if ((temp = XGetDefault(disp, 
  198.                           APPLICATION_CLASS, 
  199.                           type)) != NULL) {
  200.             sprintf(buf, "%s:%s",type,temp);
  201.             tailor_add(plist, tailor_new(buf));
  202.         } else 
  203.             tailor_add(plist,tailor_new(hardwired));
  204.     }
  205. }
  206.  
  207. static void tailor_add_defaults(plist)
  208. struct tailor    **plist;
  209. {
  210.     /* mts defaults */
  211.     tailor_add_one_default(plist, "mtsin-chan", default_mtsin_chan);
  212.     tailor_add_one_default(plist, "mtsout-chan", default_mtsout_chan);
  213.     tailor_add_one_default(plist, "mtsboth-chan", default_mtsboth_chan);
  214.     tailor_add_one_default(plist, "mtsin-mta", default_mtsin_mta);
  215.     tailor_add_one_default(plist, "mtsout-mta", default_mtsout_mta);
  216.      tailor_add_one_default(plist, "mtsboth-mta", default_mtsboth_mta);
  217.      tailor_add_one_default(plist, "mtsin-msg", default_mtsin_msg);
  218.     tailor_add_one_default(plist, "mtsout-msg", default_mtsout_msg);
  219.     tailor_add_one_default(plist, "mtsboth-msg", default_mtsboth_msg);
  220.     
  221.     /* mta defaults */
  222.     tailor_add_one_default(plist, "mtain-chan", default_mtain_chan);
  223.     tailor_add_one_default(plist, "mtaout-chan", default_mtaout_chan);
  224.     tailor_add_one_default(plist, "mtaboth-chan", default_mtaboth_chan);
  225.     tailor_add_one_default(plist, "mtain-mta", default_mtain_mta);
  226.     tailor_add_one_default(plist, "mtaout-mta", default_mtaout_mta);
  227.     tailor_add_one_default(plist, "mtaboth-mta", default_mtaboth_mta);
  228.     tailor_add_one_default(plist, "mtain-msg", default_mtain_msg);
  229.     tailor_add_one_default(plist, "mtaout-msg", default_mtaout_msg);
  230.     tailor_add_one_default(plist, "mtaboth-msg", default_mtaboth_msg);
  231.  
  232.     /* internal defaults */
  233.     tailor_add_one_default(plist, "internal-chan", default_internal_chan);
  234.     tailor_add_one_default(plist, "internal-mta", default_internal_mta);
  235.     tailor_add_one_default(plist, "internal-msg", default_internal_msg);
  236.     
  237.     /* passive defaults */
  238.     tailor_add_one_default(plist, "passive-chan", default_passive_chan);
  239.     tailor_add_one_default(plist, "passive-mta", default_passive_mta);
  240.     tailor_add_one_default(plist, "passive-msg", default_passive_msg);
  241. }
  242.  
  243.  
  244. /*   */
  245.  
  246. TaiInit()
  247. {
  248.     FILE    *fp = NULL;
  249.     char    buf[BUFSIZ];
  250.  
  251.     /* read in console tailor file */
  252.     if (tailorfile[0] != '\0') {
  253.         if ((fp  = fopen(tailorfile, "r")) == NULL
  254.             && tailorfile[0] != '/') {
  255.             char    *home;
  256.             /* try relative to home directory */
  257.             if ((home = getenv("HOME")) != NULLCP) {
  258.                 (void) sprintf(buf, "%s/%s",
  259.                            home, tailorfile);
  260.                 fp = fopen(buf, "r");
  261.             }
  262.         }
  263.         
  264.         if (fp != NULL) {
  265.             while (fgets(buf, BUFSIZ, fp) != NULLCP) {
  266.                 compress(buf, buf);
  267.                 if (buf[0] == '\n' || buf[0] == '\0' 
  268.                     || buf[0] == '#') 
  269.                     continue;
  270.                 if (strncmp(buf,"totals", strlen("totals")) == 0)
  271.                     add_total_ubs(buf);
  272.                 else
  273.                     tailor_add(&tailors, tailor_new(buf));
  274.             }
  275.             fclose(fp);
  276.         }
  277.     }
  278.     tailor_add_defaults(&tailors);
  279. }
  280.  
  281. /*   */
  282.  
  283. add_tailor_to_chan(chan)
  284. struct chan_struct    *chan;
  285. {
  286.     char    buf[BUFSIZ];
  287.     
  288.     sprintf(buf, "%s-chan", chan->channelname);
  289.     
  290.     if ((chan->tai = find_tailor(buf, tailors)) == NULL) {
  291.         /* no explicit try defaults */
  292.  
  293.         char    *type = NULL,
  294.             *dir = NULL;
  295.  
  296.         switch (chan->chantype) {
  297.             case int_Qmgr_chantype_mta:
  298.             type = strdup("mta");
  299.             if (chan->outbound > 0 && chan->inbound > 0)
  300.                 dir = strdup("both");
  301.             else if (chan->inbound > 0)
  302.                 dir = strdup("in");
  303.             else if (chan->outbound > 0)
  304.                 dir = strdup("out");
  305.             break;
  306.  
  307.             case int_Qmgr_chantype_mts:
  308.             type = strdup("mts");
  309.             if (chan->outbound > 0 && chan->inbound > 0)
  310.                 dir = strdup("both");
  311.             else if (chan->inbound > 0)
  312.                 dir = strdup("in");
  313.             else if (chan->outbound > 0)
  314.                 dir = strdup("out");
  315.             break;
  316.  
  317.             case int_Qmgr_chantype_internal:
  318.             type = strdup("internal");
  319.             break;
  320.  
  321.             case int_Qmgr_chantype_passive:
  322.             default:
  323.             type = strdup("passive");
  324.             break;
  325.         }
  326.  
  327.         sprintf(buf, "%s%s-chan",
  328.             type,
  329.             (dir == NULL) ? "" : dir);
  330.  
  331.         if (type) free(type);
  332.         if (dir) free(dir);
  333.         chan->tai = find_tailor(buf, tailors);
  334.     }
  335. }
  336.         
  337. add_tailor_to_mta(chan, mta)
  338. struct chan_struct    *chan;
  339. struct mta_struct    *mta;
  340. {
  341.     char    buf[BUFSIZ];
  342.     
  343.     sprintf(buf, "%s-mta", chan->channelname);
  344.     
  345.     if ((mta->tai = find_tailor(buf, tailors)) == NULL) {
  346.         /* no explicit try defaults */
  347.  
  348.         char    *type = NULL,
  349.             *dir = NULL;
  350.  
  351.         switch (chan->chantype) {
  352.             case int_Qmgr_chantype_mta:
  353.             type = strdup("mta");
  354.             if (chan->outbound > 0 && chan->inbound > 0)
  355.                 dir = strdup("both");
  356.             else if (chan->inbound > 0)
  357.                 dir = strdup("in");
  358.             else if (chan->outbound > 0)
  359.                 dir = strdup("out");
  360.             break;
  361.  
  362.             case int_Qmgr_chantype_mts:
  363.             type = strdup("mts");
  364.             if (chan->outbound > 0 && chan->inbound > 0)
  365.                 dir = strdup("both");
  366.             else if (chan->inbound > 0)
  367.                 dir = strdup("in");
  368.             else if (chan->outbound > 0)
  369.                 dir = strdup("out");
  370.             break;
  371.  
  372.             case int_Qmgr_chantype_internal:
  373.             type = strdup("internal");
  374.             break;
  375.  
  376.             case int_Qmgr_chantype_passive:
  377.             default:
  378.             type = strdup("passive");
  379.             break;
  380.         }
  381.  
  382.         sprintf(buf, "%s%s-mta",
  383.             type,
  384.             (dir == NULL) ? "" : dir);
  385.  
  386.         if (type) free(type);
  387.         if (dir) free(dir);
  388.         mta->tai = find_tailor(buf, tailors);
  389.     }
  390. }
  391.  
  392. add_tailor_to_msg(chan, msg)
  393. struct chan_struct    *chan;
  394. struct msg_struct    *msg;
  395. {
  396.     char    buf[BUFSIZ];
  397.     
  398.     if (chan == NULL)
  399.         return;
  400.  
  401.     sprintf(buf, "%s-msg", chan->channelname);
  402.     
  403.     if ((msg->tai = find_tailor(buf, tailors)) == NULL) {
  404.         /* no explicit try defaults */
  405.  
  406.         char    *type = NULL,
  407.             *dir = NULL;
  408.  
  409.         switch (chan->chantype) {
  410.             case int_Qmgr_chantype_mta:
  411.             type = strdup("mta");
  412.             if (chan->outbound > 0 && chan->inbound > 0)
  413.                 dir = strdup("both");
  414.             else if (chan->inbound > 0)
  415.                 dir = strdup("in");
  416.             else if (chan->outbound > 0)
  417.                 dir = strdup("out");
  418.             break;
  419.  
  420.             case int_Qmgr_chantype_mts:
  421.             type = strdup("mts");
  422.             if (chan->outbound > 0 && chan->inbound > 0)
  423.                 dir = strdup("both");
  424.             else if (chan->inbound > 0)
  425.                 dir = strdup("in");
  426.             else if (chan->outbound > 0)
  427.                 dir = strdup("out");
  428.             break;
  429.  
  430.             case int_Qmgr_chantype_internal:
  431.             type = strdup("internal");
  432.             break;
  433.  
  434.             case int_Qmgr_chantype_passive:
  435.             default:
  436.             type = strdup("passive");
  437.             break;
  438.         }
  439.  
  440.         sprintf(buf, "%s%s-msg",
  441.             type,
  442.             (dir == NULL) ? "" : dir);
  443.  
  444.         if (type) free(type);
  445.         if (dir) free(dir);
  446.         msg->tai = find_tailor(buf, tailors);
  447.     }
  448. }
  449.  
  450. /*   */
  451.  
  452. int volBadness(vol)
  453. int    vol;
  454. {
  455.     int    retval = 0;
  456.     if (ub_total_volume != 0.0)
  457.         retval = (int) (vol*100/ub_total_volume);
  458.     if (vol != 0 && retval == 0)
  459.         retval = 1;
  460.     return retval;
  461. }
  462.  
  463. int numBadness(num)
  464. int    num;
  465. {
  466.     int     retval = 0;
  467.     if (ub_total_number != 0.0) 
  468.         retval = (int) (num*100/ub_total_number);
  469.     if (num != 0 && retval == 0)
  470.         return 1;
  471.     return retval;
  472. }
  473.  
  474. extern int displayInactIns;
  475.  
  476. int chanBadness(chan)
  477. struct chan_struct    *chan;
  478. {
  479.     double        average_db = 0.0,
  480.             age,
  481.             last;
  482.     
  483.     int        average = 0,
  484.             noFactors = 0;
  485.  
  486.     register struct tailor    *tai = chan->tai;
  487.  
  488.     if (tai == NULL) {
  489.         PP_LOG(LLOG_EXCEPTIONS,
  490.                ("No tailoring for channel '%s'", chan->channelname));
  491.         return 0;
  492.     }
  493.  
  494.     if ((chan->inbound <= 0 || displayInactIns == FALSE)
  495.         && chan->numberMessages == 0 
  496.         && chan->numberReports == 0)
  497.         return 0;
  498.  
  499.     if (tai->ub_number != 0.0) {
  500.         if ((chan->numberMessages + chan->numberReports) >= tai->ub_number)
  501.             return max_bad_channel;
  502.         average_db += ((chan->numberMessages+chan->numberReports) * 100)/ tai->ub_number;
  503.         noFactors++;
  504.     }
  505.  
  506.     if (tai->ub_volume != 0.0) {
  507.         if (chan->volumeMessages >= tai->ub_volume)
  508.             return max_bad_channel;
  509.         average_db += (chan->volumeMessages * 100)/tai->ub_volume;
  510.         noFactors++;
  511.     }
  512.  
  513.     if (tai->ub_age != 0.0) {
  514.         if (chan->oldestMessage != 0 && 
  515.             (chan->numberMessages != 0 || chan->numberReports != 0))
  516.             age = (currentTime-chan->oldestMessage) / 60.0;
  517.         else
  518.             age = 0.0;
  519.         if (age >= tai->ub_age)
  520.             return max_bad_channel;
  521.         average_db += (age * 100)/tai->ub_age;
  522.         noFactors++;
  523.     }
  524.  
  525.     if (tai->ub_last != 0.0) {
  526.         if (chan->status->lastSuccess != 0)
  527.             last = (currentTime - chan->status->lastSuccess)/60.0;
  528.         else
  529.             last = 0.0;
  530.         if (last >= tai->ub_last)
  531.             return max_bad_channel;
  532.         if (last >= tai->ub_last/2) {
  533.             average_db += (last * 100)/tai->ub_last;
  534.             noFactors++;
  535.         }
  536.     }
  537.  
  538.     /* scale up those that don't use all factors */
  539.     if (noFactors != 0)
  540.         average = (int) (average_db * max_bad_channel / (noFactors * 100));
  541.  
  542.     if (average == 0 && average_db != 0.0)
  543.         return 1;
  544.     return average;
  545. }
  546.  
  547. /*   */
  548.  
  549. int mtaBadness(mta)
  550. struct mta_struct    *mta;
  551. {
  552.     double        average_db = 0.0,
  553.             age,
  554.             last;
  555.     
  556.     int        average = 0,
  557.             noFactors = 0;
  558.  
  559.     register struct tailor    *tai = mta->tai;
  560.  
  561.     if (tai == NULL) {
  562.         PP_LOG(LLOG_EXCEPTIONS,
  563.                ("No tailoring for mta '%s'", mta->mta));
  564.         return 0;
  565.     }
  566.  
  567.     if (mta->numberMessages == 0 && mta->numberReports == 0)
  568.         return 0;
  569.  
  570.     if (tai->ub_number != 0.0) {
  571.         if (mta->numberMessages+mta->numberReports >= tai->ub_number)
  572.             return max_bad_mta;
  573.         average_db += ((mta->numberMessages+mta->numberReports) * 100)/ tai->ub_number;
  574.         noFactors++;
  575.     }
  576.  
  577.     if (tai->ub_volume != 0.0) {
  578.         if (mta->volumeMessages >= tai->ub_volume)
  579.             return max_bad_mta;
  580.         average_db += (mta->volumeMessages * 100)/tai->ub_volume;
  581.         noFactors++;
  582.     }
  583.  
  584.     if (tai->ub_age != 0.0) {
  585.         if (mta->oldestMessage != 0 
  586.             && (mta->numberMessages != 0 || mta->numberReports != 0))
  587.             age = (currentTime-mta->oldestMessage) / 60.0;
  588.         else
  589.             age = 0;
  590.         if (age >= tai->ub_age)
  591.             return max_bad_mta;
  592.         average_db += (age * 100)/tai->ub_age;
  593.         noFactors++;
  594.     }
  595.  
  596.     if (tai->ub_last != 0.0) {
  597.         if (mta->status->lastSuccess != 0)
  598.             last = (currentTime - mta->status->lastSuccess)/60.0;
  599.         else
  600.             last = 0;
  601.         if (last >= tai->ub_last)
  602.             return max_bad_mta;
  603.         if (last >= tai->ub_last/2) {
  604.             average_db += (last * 100)/tai->ub_last;
  605.             noFactors++;
  606.         }
  607.     }
  608.  
  609.     /* scale up those that don't use all factors */
  610.     if (noFactors != 0)
  611.         average = (int) (average_db * max_bad_mta / (noFactors * 100));
  612.  
  613.     if (average == 0 && average_db != 0.0)
  614.         return 1;
  615.     return average;
  616. }
  617.  
  618. /*   */
  619.  
  620. int msgBadness(msg)
  621. struct msg_struct    *msg;
  622. {
  623.     double        average_db = 0.0,
  624.             age;
  625.     
  626.     int        average = 0,
  627.             noFactors = 0;
  628.  
  629.     register struct tailor    *tai = msg->tai;
  630.  
  631.     if (tai == NULL) {
  632.         PP_LOG(LLOG_EXCEPTIONS,
  633.                ("No tailoring for msg '%s'", msg->msginfo->queueid));
  634.         return 0;
  635.     }
  636.  
  637.     if (msg->msginfo->expiryTime != 0
  638.         && (currentTime - msg->msginfo->expiryTime) >= 0)
  639.         /* expired so max_bad_msg ?? */
  640.         return max_bad_msg;
  641.  
  642.     if (tai->ub_age != 0.0) {
  643.         age = (currentTime-msg->msginfo->age) / 60.0;
  644.         if (age >= tai->ub_age)
  645.             return max_bad_msg;
  646.         average_db += (age * 100)/tai->ub_age;
  647.         noFactors++;
  648.     }
  649.  
  650.     if (tai->ub_volume != 0.0) {
  651.         if (msg->msginfo->size > tai->ub_volume)
  652.             return max_bad_msg;
  653.         average_db += (msg->msginfo->size * 100) / tai->ub_volume;
  654.         noFactors++;
  655.     }
  656.  
  657.     /* scale up those that don't use all factors */
  658.     if (noFactors != 0)
  659.         average = (int) (average_db * max_bad_msg / (noFactors * 100));
  660.     if (average == 0 && average_db != 0.0)
  661.         return 1;
  662.     return average;
  663. }
  664.  
  665. /*   */
  666. /* colour routines */
  667. extern struct color_item     *colors;
  668. extern XColor            white,
  669.                 black;
  670. extern Pixel            fg, bg;
  671. extern int            num_colors;
  672.  
  673. unsigned long volcolourOf(vol)
  674. int    vol;
  675. {
  676.     int    bad,
  677.         ix;
  678.     bad = volBadness(vol);
  679.     if (bad == 0)
  680.         return bg;
  681.     else {
  682.         ix = bad*num_colors/ub_total_volume;
  683.         if (ix >= num_colors)
  684.             ix = num_colors-1;
  685.         return colors[ix].colour.pixel;
  686.     }
  687. }
  688.  
  689. unsigned long numcolourOf(num)
  690. int    num;
  691. {
  692.     int    bad,
  693.         ix;
  694.     bad = numBadness(num);
  695.     if (bad == 0)
  696.         return bg;
  697.     else {
  698.         ix = bad*num_colors/ub_total_number;
  699.         if (ix >= num_colors)
  700.             ix = num_colors-1;
  701.         return colors[ix].colour.pixel;
  702.     }
  703. }
  704.  
  705. unsigned long chancolourOf (chan)
  706. struct chan_struct    *chan;
  707. {
  708.     int    bad,
  709.         ix;
  710.     /* find nearest index to chanBadness(chan)'s value */
  711.     /* always round up at moment */
  712.     bad = chanBadness(chan);
  713.     if (bad == 0) 
  714.         /* output white border colour */
  715.         return bg;
  716.     else {
  717.         ix = bad*num_colors/max_bad_channel;
  718.         if (ix >= num_colors)
  719.             ix = num_colors-1;
  720.         return colors[ix].colour.pixel;
  721.     }
  722. }
  723.  
  724. unsigned long mtacolourOf (mta)
  725. struct mta_struct    *mta;
  726. {
  727.     int    bad,
  728.         ix;
  729.     /* find nearest index to mtaBadness(mta)'s value */
  730.     /* always round up at moment */
  731.     bad = mtaBadness(mta);
  732.     if (bad == 0) 
  733.         /* output white border colour */
  734.         return bg;
  735.     else {
  736.         ix = bad*num_colors/max_bad_mta;
  737.         if (ix >= num_colors)
  738.             ix = num_colors-1;
  739.         return colors[ix].colour.pixel;
  740.     }
  741. }
  742.     
  743. unsigned long msgcolourOf (msg)
  744. struct msg_struct    *msg;
  745. {
  746.     int    bad,
  747.         ix;
  748.     /* find nearest index to msgBadness(msg)'s value */
  749.     /* always round up at moment */
  750.     bad = msgBadness(msg);
  751.     if (bad == 0)
  752.         return bg;
  753.     else {
  754.         ix = bad*num_colors/max_bad_msg;
  755.         if (ix >= num_colors)
  756.             ix = num_colors-1;
  757.         return colors[ix].colour.pixel;
  758.     }
  759.  
  760. }
  761.  
  762. /*   */
  763. /* border routines */
  764. extern int    max_chan_border,
  765.         max_mta_border,
  766.         max_msg_border;
  767.  
  768. int chanborderOf(chan)
  769. struct chan_struct    *chan;
  770. {
  771.     int    bad,
  772.         wid;
  773.     bad = chanBadness(chan);
  774.     if (bad == 0)
  775.         return 1;
  776.     else {
  777.         wid = max_chan_border*bad/max_bad_channel + 1;
  778.         if (wid > max_chan_border)
  779.             wid = max_chan_border;
  780.         return wid;
  781.     }
  782. }
  783.  
  784.  
  785. int mtaborderOf(mta)
  786. struct mta_struct    *mta;
  787. {
  788.     int    bad,
  789.         wid;
  790.     bad = mtaBadness(mta);
  791.     if (bad == 0)
  792.         return 1;
  793.     else {
  794.         wid = max_mta_border*bad/max_bad_mta + 1;
  795.         if (wid > max_mta_border)
  796.             wid = max_mta_border;
  797.         return wid;
  798.     }
  799. }
  800.  
  801. int msgborderOf(msg)
  802. struct msg_struct    *msg;
  803. {
  804.     int    bad,
  805.         wid;
  806.     bad = msgBadness(msg);
  807.     if (bad == 0)
  808.         return 1;
  809.     else {
  810.         wid = max_msg_border*bad/max_bad_msg + 1;
  811.         if (wid > max_msg_border)
  812.             wid = max_msg_border;
  813.         return wid;
  814.     }
  815. }
  816.  
  817. /*   */
  818.  
  819. /* ordering routines */
  820. extern int            num_channels;
  821. extern struct chan_struct    **ordered_list;
  822.  
  823. static int channel_compare(one, two)
  824. struct chan_struct    **one,
  825.             **two;
  826. /* return -1 if one worse state then two */
  827. {
  828.     int    onebad,
  829.         twobad;
  830.     onebad = chanBadness((*one));
  831.     twobad = chanBadness((*two));
  832.     if (onebad < twobad)
  833.         return 1;
  834.     else if (onebad > twobad)
  835.         return -1;
  836.     else 
  837.         return 0;
  838. }
  839.  
  840. order_display_channels()
  841. /* order display_list */
  842. {
  843.     qsort((char *) &(ordered_list[0]),num_channels,
  844.           sizeof(ordered_list[0]),(IFP)channel_compare);
  845. }
  846.  
  847.  
  848. static int mta_compare (one, two)
  849. struct mta_struct    **one,
  850.             **two;
  851. /* returns -1 if ione in worse state than two */
  852. {
  853.     int    onebad,
  854.         twobad;
  855.     onebad = mtaBadness((*one));
  856.     twobad = mtaBadness((*two));
  857.     if (onebad < twobad)
  858.         return 1;
  859.     else if (onebad > twobad)
  860.         return -1;
  861.     else 
  862.         return 0;
  863. }
  864.  
  865. order_mtas(plist,num)
  866. struct mta_struct    ***plist;
  867. int            num;
  868. {
  869.     struct mta_struct **temp = *plist;
  870.     qsort((char *)&(temp[0]),num,sizeof(temp[0]),(IFP)mta_compare);
  871. }
  872.  
  873. extern int            number_msgs;
  874. extern struct msg_struct    **global_msg_list;
  875.  
  876. static int msg_compare (one, two)
  877. struct msg_struct    **one,
  878.             **two;
  879. /* returns -1 if ione in worse state than two */
  880. {
  881.     int    onebad,
  882.         twobad;
  883.     onebad = msgBadness((*one));
  884.     twobad = msgBadness((*two));
  885.     if (onebad < twobad)
  886.         return 1;
  887.     else if (onebad > twobad)
  888.         return -1;
  889.     else 
  890.         return 0;
  891. }
  892.  
  893. order_msgs()
  894. {
  895.     qsort((char *) &(global_msg_list[0]),number_msgs,
  896.           sizeof(global_msg_list[0]),(IFP)msg_compare);
  897. }
  898.  
  899. /*   */
  900.  
  901. int    NumVertLines(chan)
  902. struct chan_struct    *chan;
  903. {
  904.     int    ret = 1 + (max_vert_lines * chanBadness(chan))/max_bad_channel;
  905.     return ret;
  906. }
  907.  
  908. extern XFontStruct        *disabledFont,
  909.                 *activeFont,
  910.                 *normalFont;
  911.  
  912. XFontStruct    *chanFont(chan)
  913. struct chan_struct    *chan;
  914. {
  915.     if (chan == NULL)
  916.         return normalFont;
  917.  
  918.     if (chan->status->enabled == FALSE)
  919.         return disabledFont;
  920.     else if (chan->numberActiveProcesses > 0)
  921.         return activeFont;
  922.     else
  923.         return normalFont;
  924. }
  925.     
  926. XFontStruct    *mtaFont(mta)
  927. struct mta_struct    *mta;
  928. {
  929.     if (mta == NULL)
  930.         return normalFont;
  931.  
  932.     if (mta->status->enabled == FALSE)
  933.         return disabledFont;
  934.     else if (mta -> active)
  935.         return activeFont;
  936.     else
  937.         return normalFont;
  938. }
  939.  
  940. XFontStruct    *msgFont(msg)
  941. struct msg_struct    *msg;
  942. {
  943.     struct recip    *ix;
  944.  
  945.     if (msg == NULL)
  946.         return normalFont;
  947.         
  948.     ix = msg->reciplist;
  949.  
  950.     while (ix != NULL) {
  951.         if (ix -> status -> enabled == FALSE)
  952.             return disabledFont;
  953.         ix = ix -> next;
  954.     }
  955.     return normalFont;
  956. }
  957.